import { AmbientLight, BoxGeometry, CylinderGeometry, DirectionalLight, Group, HemisphereLight, Mesh, Object3D, OrthographicCamera, PerspectiveCamera, PlaneGeometry, PointLight, RectAreaLight, SphereGeometry, SpotLight, Vector3 } from "three";
import { TezeroCommponent, Tezero } from "../index";
import SpriteText from 'three-spritetext';
import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader.js';
import { ColladaLoader } from 'three/examples/jsm/loaders/ColladaLoader';
import {CSS3DObject} from 'three/examples/jsm/renderers/CSS3DRenderer.js';

function setPosition(data: TezeroCommponent,mesh:Object3D){
    if(data.position){
        mesh.position.copy(data.position);
    }
}

export function group(data: TezeroCommponent): Object3D {
    const group = new Group();
    group.name = '组';
    setPosition(data,group);
    return group;
}

export function box(data: TezeroCommponent): Object3D {
    const geometry = new BoxGeometry(data.width, data.height, data.depth, data.widthSegments, data.heightSegments, data.depthSegments);
    const mesh = new Mesh(geometry, Tezero.createMaterial(data.materialType, data.material));
    mesh.name = '立方体';
    setPosition(data,mesh);
    return mesh;
}

export function plane(data: TezeroCommponent): Object3D {
    const geometry = new PlaneGeometry(data.width, data.height, data.widthSegments, data.heightSegments);
    const mesh = new Mesh(geometry, Tezero.createMaterial(data.materialType, data.material));
    mesh.name = '平面';
    mesh.rotation.x = -Math.PI / 2;
    setPosition(data,mesh);
    return mesh;
}

export function sphere(data: TezeroCommponent): Object3D {
    const geometry = new SphereGeometry(data.radius, data.widthSegments, data.heightSegments, data.phiStart, data.phiLength, data.thetaStart, data.thetaLength);
    const mesh = new Mesh(geometry, Tezero.createMaterial(data.materialType, data.material));
    mesh.name = '圆球体';
    setPosition(data,mesh);
    return mesh;
}

export function cylinder(data: TezeroCommponent): Object3D {
    const geometry = new CylinderGeometry(data.radiusTop, data.radiusBottom, data.height, data.radialSegments, data.heightSegments, data.openEnded, data.thetaStart, data.thetaLength);
    const mesh = new Mesh(geometry, Tezero.createMaterial(data.materialType, data.material));
    mesh.name = '圆柱体';
    return mesh;

}

export function text2d(data: TezeroCommponent): Object3D {

    const text = new SpriteText(data.text, data.textHeight, data.color);
    if (data.backgroundColor) {
        text.backgroundColor = data.backgroundColor;
    }
    if (data.color) {
        text.color = data.color;
    }
    if (data.strokeWidth) {
        text.strokeWidth = data.strokeWidth;
    }
    if (data.strokeColor) {
        text.strokeColor = data.strokeColor;
    }
    if (data.fontFace) {
        text.fontFace = data.fontFace;
    }
    if (data.fontSize) {
        text.fontSize = data.fontSize;
    }
    if (data.fontWeight) {
        text.fontWeight = data.fontWeight;
    }
    if (data.padding) {
        text.padding = data.padding;
    }
    if (data.borderWidth) {
        text.borderWidth = data.borderWidth;
    }
    if (data.borderRadius) {
        text.borderRadius = data.borderRadius;
    }
    if (data.borderColor) {
        text.borderColor = data.borderColor;
    }
    text.userData = {
        text: {
            text: data.text,
            color: data.color,
            backgroundColor: data.backgroundColor,
            strokeWidth: data.strokeWidth,
            strokeColor: data.strokeColor,
            fontFace: data.fontFace,
            fontSize: data.fontSize,
            fontWeight: data.fontWeight,
            padding: data.padding,
            borderWidth: data.borderWidth,
            borderRadius: data.borderRadius,
            borderColor: data.borderColor
        },
        isText: true,
    };
    text.scale.x = text.scale.x / text.scale.y;
    text.scale.y = 1;
    text.name = data.text;
    setPosition(data,text);
    return text;
}


export function directionalLight(data: TezeroCommponent): Object3D {
    const light = new DirectionalLight(data.color, data.intensity);
    light.name = '平行光';
    
    setPosition(data,light);
    return light;
}

export function ambientLight(data: TezeroCommponent): Object3D {
    const light = new AmbientLight(data.color, data.intensity);
    light.name = '环境光';
    setPosition(data,light);
    return light;
}
export function hemisphereLight(data: TezeroCommponent): Object3D {
    const light = new HemisphereLight(data.skyColor, data.groundColor, data.intensity);
    light.name = '半球光';
    setPosition(data,light);
    return light;
}
export function pointLight(data: TezeroCommponent): Object3D {
    const light = new PointLight(data.color, data.intensity, data.distance, data.decay);
    light.name = '点光源';
    if (data.power !== undefined || data.power !== null) {
        light.power = data.power;
    }
    setPosition(data,light);
    return light;
}
export function spotLight(data: TezeroCommponent): Object3D {
    const light = new SpotLight(data.color, data.intensity, data.distance, data.angle, data.penumbra, data.decay);
    light.name = '聚光灯';
    if (data.power !== undefined || data.power !== null) {
        light.power = data.power;
    }
    light.castShadow = true
    setPosition(data,light);
    return light;
}
export function rectAreaLight(data: TezeroCommponent): Object3D {
    const light = new RectAreaLight(data.color, data.intensity, data.width, data.height);
    light.name = '平面光光源';
    if (data.power !== undefined || data.power !== null) {
        light.power = data.power;
    }
    setPosition(data,light);
    return light;
}

export function perspectiveCamera(data: TezeroCommponent): Object3D {
    const camera = new PerspectiveCamera(data.fov, data.aspect, data.near, data.far);
    camera.lookAt(new Vector3());
    camera.name = '透视相机';
    setPosition(data,camera);
    return camera;
}
export function orthographicCamera(data: TezeroCommponent): Object3D {
    const camera = new OrthographicCamera(data.left, data.right, data.top, data.bottom, data.near, data.far);
    camera.lookAt(new Vector3());
    camera.name = '正交相机';
    setPosition(data,camera);
    return camera;
}

export function fbx(data: TezeroCommponent): Object3D|Promise<Object3D> {
    // const buf = fetch(data.url);
    const loader = new FBXLoader();
    
    // return object;
    return new Promise(async (resolve,reject)=>{
        try{
            const res=await fetch(data.url);
            const buf=await res.arrayBuffer();
            const object = loader.parse(buf as any, undefined);
            object.name = data.name || 'FBX模型';
            
            setPosition(data,object);
            resolve(object);
        }catch(e){
            reject(e);
        }
    });
}

export function dae(data: TezeroCommponent): Object3D|Promise<Object3D> {
    // const buf = fetch(data.url);
    const loader = new ColladaLoader();
    
    // return object;
    return new Promise(async (resolve,reject)=>{
        try{
            const res=await fetch(data.url);
            const buf=await res.arrayBuffer();
            const collada = loader.parse(buf as any, undefined);
            const object=collada.scene;
            object.name = data.name || 'DAE模型';
            setPosition(data,object);
            resolve(object);
        }catch(e){
            reject(e);
        }
    });
}


export function domButton(data: TezeroCommponent): Object3D {
    const dom= document.createElement('button');
    dom.innerText=data.text||'按钮';
    dom.style.pointerEvents='none';
    dom.style.backgroundColor='#23232333';
    dom.style.padding="2px 10px";
    const object = new Tezero.DomObject(dom);
    object.name = 'CSS按钮';
    setPosition(data,object);
    object.scale.x=0.02;
    object.scale.y=0.02;
    object.scale.z=0.02;
    object.userData = {
        html: {
            text: data.text
        },
    };
    return object;
}